﻿using System;
using TradeHelp.Utilities;

namespace TradeHelp.MaterializedObjectViews.Helpers
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TInput"></typeparam>
    /// <typeparam name="TOutput"></typeparam>
    internal class ViewMsgStream<TInput, TOutput> : IViewStream<TOutput>, IDisposable
    {
        private readonly IViewStream<TInput> _provider;
        private readonly Func<ViewMessageBurst<TInput>, ViewMessageBurst<TOutput>> _transformer;
        private StreamMessageDelegate<TOutput> _callbacks;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="transformer"></param>
        public ViewMsgStream(IViewStream<TInput> provider, Func<ViewMessageBurst<TInput>, ViewMessageBurst<TOutput>> transformer)
        {
            Invariant.CheckIsNull(provider, "provider");
            Invariant.CheckIsNull(transformer, "transformer");
            _provider = provider;
            _transformer = transformer;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callback"></param>
        public void StreamData(StreamMessageDelegate<TOutput> callback)
        {
            _callbacks += callback;
            _provider.StreamData(MsgHandler);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callback"></param>
        public void Unsubscribe(StreamMessageDelegate<TOutput> callback)
        {
            _callbacks -= callback;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="burst"></param>
        private void MsgHandler(ViewMessageBurst<TInput> burst)
        {
            var callbacks = _callbacks;
            if (callbacks != null)
                callbacks(_transformer(burst));
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            _callbacks = null;
            _provider.Unsubscribe(MsgHandler);
            var disposable = _provider as IDisposable;
            if(disposable != null)
            {
                disposable.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("ViewMsgStream[{0},{1}]", typeof(TInput), typeof(TOutput));
        }
    }
}